dojo.provide("apt.CalendarComponent");
dojo.require("apt.CalendarDay");
dojo.require("dijit._WidgetBase");
dojo.require("dijit.WidgetSet");
dojo.require("dijit._TemplatedMixin");

dojo.declare("apt.CalendarComponent", [dijit._WidgetBase, dijit._TemplatedMixin], {
    templateString: dojo.cache('apt.templates', 'CalendarComponent.html'),
    widgetsInTemplate: true,
    days: [],
    startDate: "",
    daysShowing: "",
    leftOffsetInDays: 7,
    quotient: 3,
    displayArea: {},
    parent: '',
    dragHandle: {},
    scrollThrottle: '',
    scrollEventHandler: '',

    constructor: function (data) {
        this.inherited(arguments);
        dojo.safeMixin(this, data);
        this.daysShowing = this.parent.daysShowing;
        this.autoReload = 15 * 60 * 1000;
        this.leftOffsetInDays = parseInt((this.quotient * this.daysShowing - this.daysShowing) / 2);
    },

    postCreate: function () {
        dojo.connect(this.containerNode, 'onmousedown', this, this.dragStart);
        this.scrollEventHandler = dojo.connect(this.domNode, 'onscroll', this, this.scrollHandlerThrottled);

    },

    startup: function () {
        this.generateDays();
        dojo.when(this.parent.stores.resx.query({type: "settings"})
            , dojo.hitch(this, function (result) {
                //debugger
                var autoReload = (parseFloat(result["autoReload"] || "15") * 60 * 1000) || this.autoReload;
                if (autoReload > 0) {
                    //console.log("settings: " + JSON.stringify(result) + ", autoReload: " + autoReload);
                    setInterval(dojo.hitch(this, this.reload), autoReload);
                }
            }), dojo.hitch(this, function (result) {
                // error --> default 15m
                //console.log("default: 15m " + result);
                if (this.autoReload > 0) {
                    setInterval(dojo.hitch(this, this.reload), this.autoReload);
                }
            })
        );
    },

    dragStart: function (event) {
        this.dragHandle.moveHandler = dojo.connect(document, 'onmousemove', this, this.dragMove);
        this.dragHandle.endHandler = dojo.connect(document, 'onmouseup', this, this.dragEnd);
        this.dragHandle.x = event.clientX;
        dojo.style(document.body, 'cursor', 'move');
        dojo.style(document.body, 'cursor', '-webkit-grab');
    },

    dragMove: function (event) {
        var xdiff = event.clientX - this.dragHandle.x;
        this.dragHandle.x = event.clientX;
        this.domNode.scrollLeft = this.domNode.scrollLeft - xdiff;
    },

    dragEnd: function (event) {
        dojo.disconnect(this.dragHandle.moveHandler);
        dojo.disconnect(this.dragHandle.endHandler);
        dojo.style(document.body, 'cursor', 'default');
        if (Math.abs(this.dragHandle.original_x - event.clientX) > 4) {
            dojo.stopEvent(event);
        }
        ;
    },

    generateDays: function () {

        //if (this.scrollEventHandler) { // !== ''
        //    dojo.disconnect(this.scrollEventHandler);
        //    this.scrollEventHandler; // = '';
        //}

        for (var i = 0; i < this.days.length; i++) {
            this.days[i].delete();
        }
        ;
        this.days = [];

        var dayWidth = dojo.position(this.containerNode).w / this.daysShowing;
        //Add empty days as padding around the view.
        var dayViewRange = 84; //this.daysShowing * this.quotient; //<-- fix go mad dayViewRange >= (max dayView * quotient)
        //console.log('Range view days: ' + dayViewRange);
        var leftOffset = this.leftOffsetInDays - this.quotient;
        var rightOffset = this.leftOffsetInDays + parseInt(this.daysShowing) + this.quotient;
        for (var i = 0; i < dayViewRange; i++) {
            // Fix the begining load
            var renderBoolean = (i >= leftOffset && i <= rightOffset) ? true : false;
            var tomorrow = this.getTomorrow(this.startDate, i - this.leftOffsetInDays);
//            console.log(renderBoolean
//                + ", i: " + i +
//                ", leftOffset: " + leftOffset +
//            ", rightOffset: " + rightOffset
//            + ", tomorrow:" + tomorrow);
            var day = new apt.CalendarDay({
                date: tomorrow,
                parent: this,
                brain: this.parent,
                isShowing: renderBoolean,
                width: dayWidth
            });
            //console.log(tomorrow)
            this.days.push(day);
            day.placeAt(this.containerNode);
            day.startup();
        }
        ;
        //this.scrollEventHandler = dojo.connect(this.domNode, 'onscroll', this, this.scrollHandlerThrottled);
    },

    regenerateDays: function (value) {
        //debugger;
       // alert(value);
        var istoday = false;
        if (value === "today") {
            istoday = true;
            var today = new Date();
           // alert(this.startDate);
            value = Math.round((today - this.startDate) / 86400000) - 1;
        }
        value = parseInt(value);
        var dayShowing = parseInt(this.daysShowing);
        //alert(this.daysShowing);
        if (value < 0) {
            // previous (month + week)
            if (istoday){
                var filterObj = dojo.queryToObject(window.location.search.replace("?", ""));
                var queryStr = dojo.mixin(filterObj, {
                    daysShowing : this.daysShowing
                });
                var params = dojo.objectToQuery(queryStr);
                var redirect2 = location.origin + location.pathname + "?" + params;
                //console.log(redirect2);
                self.location = redirect2;

            } else if (value >= this.getMaximumLeftOffsetInDaysLeft()) {
                var offset = value * dojo.position(this.domNode).w / this.daysShowing;

                this.startDate.setDate(this.startDate.getDate() + value + dayShowing);
                this.domNode.scrollLeft += offset;
                this.scrollHandler();
            } else {
                // calculate day to go.
                if (this.days && this.days.length > dayShowing) {
                    var startDate = this.days[dayShowing];
                    this.startDate.setDate(startDate.date.getDate() + value );
                } else {
                    this.startDate.setDate(this.startDate.getDate() + value );
                }
                this.generateDays();
            }
        } else if (value > 0) {
            // next (month + week)
            if (istoday){
                //location.reload();
                var filterObj = dojo.queryToObject(window.location.search.replace("?", ""));
                var queryStr = dojo.mixin(filterObj, {
                    daysShowing : this.daysShowing
                });
                var params = dojo.objectToQuery(queryStr);
                var redirect2 = location.origin + location.pathname + "?" + params;
                //console.log(redirect2);
                self.location = redirect2;

            } else if (value <= this.getMaximumLeftOffsetInDaysRight()) {
                var offset = value * dojo.position(this.domNode).w / this.daysShowing;

                this.startDate.setDate(this.startDate.getDate() + value + dayShowing);
                this.domNode.scrollLeft += offset;
                this.scrollHandler();
            } else {
                // calculate day to go.
                if (this.days && this.days.length > dayShowing) {
                    var startDate = this.days[dayShowing];
                    this.startDate.setDate(startDate.date.getDate() + value );
                } else {
                    this.startDate.setDate(this.startDate.getDate() + value );
                }
                this.generateDays();
            }
        } else {
           // this.scrollHandler();
        }
    },

    resizeCalendarComponentHeight: function () {
        var cont = dojo.marginBox(this.containerNode);

        dojo.style(this.containerNode, 'height', 'auto');
        if (cont.h + cont.t < document.height) {
            dojo.style(this.containerNode, 'height', document.height - cont.t + 44 + 'px');
        }
    },

    scrollHandlerThrottled: function (event) {
        //console.log(event);
        //debugger;
        clearTimeout(this.scrollThrottle);
        this.scrollThrottle = setTimeout(dojo.hitch(this, this.scrollHandler), 100);
    },

    scrollHandler: function () {
        var days = this.daysShowing * this.quotient;

        var pos = dojo.position(this.domNode);
        var left = this.domNode.scrollLeft;
        var right = pos.x + pos.w;
        var displayWidth = pos.w;
        var dayWidth = displayWidth / this.daysShowing;
        var firstIndexShowing = parseInt(left / dayWidth);
        var lastIndexShowing = parseInt(right / dayWidth);

        var paddingInDays = parseInt((days - this.daysShowing) / 2);

        var howMany = paddingInDays - firstIndexShowing;
        if (howMany > 0) {
            this.shiftLeft(howMany);
        } else if (howMany < 0) {
            this.shiftRight(Math.abs(howMany));
        }

        this.setLeftOffsetInDays();
    },

    shiftLeft: function (count) {
        if (typeof count == 'undefined') {
            count = 1;
        }

        this.startDate.setDate(this.startDate.getDate() - count);
        this.showVisible(-count);

        var newDays = [];
        var dayLength = dojo.position(this.domNode).w / this.daysShowing;

        for (var i = count; i >= 1; i--) {
            var day = new apt.CalendarDay({
                date: this.getTomorrow(this.days[0].date, -i),
                parent: this,
                brain: this.parent,
                isShowing: false,
                width: dayLength
            });
            newDays.push(day);
        }
        ;

        for (var i = newDays.length - 1; i >= 0; i--) {
            newDays[i].placeAt(this.containerNode, 'first');
            newDays[i].startup();
        }
        ;

        this.domNode.scrollLeft += dayLength * count;

        for (var i = newDays.length - 1; i >= 0; i--) {
            var drop = this.days[this.days.length - 1];
            this.days.unshift(newDays[i]);
            this.days.splice(-1, 1);
            drop.delete();
        }
        ;

    },

    shiftRight: function (count) {
        if (typeof count == 'undefined') {
            count = 1;
        }

        this.startDate.setDate(this.startDate.getDate() + count);
        this.showVisible(count);

        var newDays = [];
        var dayLength = dojo.position(this.domNode).w / this.daysShowing;

        for (var i = count; i >= 1; i--) {
            var day = new apt.CalendarDay({
                date: this.getTomorrow(this.days[this.days.length - 1].date, i),
                parent: this,
                brain: this.parent,
                isShowing: false,
                width: dayLength
            });
            newDays.push(day);
        }
        ;

        for (var i = newDays.length - 1; i >= 0; i--) {
            newDays[i].placeAt(this.containerNode, 'last');
        }
        ;

        this.domNode.scrollLeft -= dayLength * count;

        for (var i = newDays.length - 1; i >= 0; i--) {
            newDays[i].startup();

            var drop = this.days[0];
            this.days.push(newDays[i]);
            this.days.splice(0, 1);
            drop.delete();
        }
        ;
    },

    showVisible: function (offset) {
        var daylen = this.daysShowing * this.quotient;
        var daymax = this.days.length;
        var padding = parseInt((this.daysShowing * this.quotient - this.daysShowing) / 2) + offset;
        for (var i = 0; i < daylen && i < daymax; i++) {
                this.days[i].setShowing();
            
//            if (i > padding - 1 && i < padding + this.daysShowing + 1) {
//                this.days[i].setShowing();
//            } else if (i < padding - this.daysShowing / 2 || i > padding + this.daysShowing / 2) {
//                this.days[i].setIsHidden();
//            }
        }
        ;
    },

    getPrev: function () {
        return this.days.length / 3 - 1;
    },

    getNext: function () {
        return this.days.length / 3 * 2;
    },

    loadDataForDay: function (index) {
        this.days[index].setShowing();
    },

    getMaximumLeftOffsetInDaysLeft: function () {
        var days = this.daysShowing * this.quotient;
        var padding = parseInt((days - this.daysShowing) / 2);
        return -padding;
    },

    getMaximumLeftOffsetInDaysRight: function () {
        var days = this.daysShowing * this.quotient;
        var padding = parseInt((days - this.daysShowing) / 2);
        return days - padding;
    },

    setLeftOffsetInDays: function () {
        this.leftOffsetInDays = this.domNode.scrollLeft / dojo.position(this.domNode).w * this.daysShowing;
    },

    getTomorrow: function (d, offset) {
        return new Date(d.getTime() + (86400000 * offset));
    },

    resizeCalendarComponent: function () {
        this.resizeCalendarComponentHeight();
        var width = 0;
        for (var i = 0; i < this.days.length; i++) {
            width += dojo.position(this.days[i].domNode).w;
        }
        ;

        dojo.style(this.containerNode, 'width', width + "px");

        var offset = width / this.days.length * this.leftOffsetInDays;
        this.domNode.scrollLeft = offset;
        this.setLeftOffsetInDays();
    },

    resize: function () {
        // console.log(this.parent.contentContainer.scrollLeft);
        var viewPortSize = dojo.position(this.domNode).w;
        this.daysShowing = this.parent.daysShowing;
        for (var i = 0; i < this.days.length; i++) {
            this.days[i].resize(viewPortSize);
        }
        ;

        this.resizeCalendarComponent();
    },
    
    reload: function () {
        for (var i = 0; i < this.days.length; i++) {
            this.days[i].reload();
        }
    }
});

